package org.hit.burkun.dbimport;

import java.nio.charset.Charset;
import java.util.LinkedList;

import org.hit.burkun.db.DBHelper;
import org.hit.burkun.db.DBTypeConverter;
import org.hit.burkun.file.FileProcessHelper;
import org.hit.burkun.file.IDataLineProcesser;
import org.hit.burkun.file.FileProcessHelper.FILE_TYPE;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FileBaseImport {
	private FILE_TYPE fileType;
	private String tableName;
	private int totalPropertyNum;
	private boolean hasAutoIncreasementId = true;
	private DBTypeConverter typeConverter;
	private DBHelper dbHelper;
	private LINE_SPLITER spliterType;

	private boolean useCommentStr = false;
	private int beginLineNum;
	private String commentBeginStr;
	private FileProcessHelper dataHelper;
	private int batchImportNum = 1000;

	private static Logger logger = LoggerFactory
			.getLogger(FileBaseImport.class);

	public enum LINE_SPLITER {
		TAB, COMMA
	}

	public FileBaseImport(String fullFileName, FILE_TYPE fileType,
			String tableName, DBHelper dbHelper, int totalPropertyNum,
			boolean hasAutoIncreasementID, DBTypeConverter typeConverter,
			LINE_SPLITER spliterType) {
		this.fileType = fileType;
		this.tableName = tableName;
		this.dbHelper = dbHelper;
		this.totalPropertyNum = totalPropertyNum;
		this.hasAutoIncreasementId = hasAutoIncreasementID;
		this.typeConverter = (DBTypeConverter) typeConverter.clone();
		this.spliterType = spliterType;
		dataHelper = new FileProcessHelper(fullFileName, Charset.forName("utf8"));
	}

	// 对每个item进行处理
	protected String[] forEachItem(String[] items) {
		return items;
	}

	public void setBatchImportNumber(int num) {
		this.batchImportNum = num;
	}

	public void doImport(int beginLineNum) {
		this.useCommentStr = false;
		this.beginLineNum = beginLineNum;
		imp();
	}

	public void doImport(String commentBeginStr) {
		this.useCommentStr = true;
		this.commentBeginStr = commentBeginStr;
		imp();
	}

	private void imp() {
		dbHelper.connectionDB();
		dataHelper.process(new IDataLineProcesser() {

			private LinkedList<String[]> linkedList = new LinkedList<String[]>();
			private int counter = 0;
			private int autoIncreasementId = 0;
			private int curLineNumber = 0;
			// variable
			private int itemNum = totalPropertyNum;
			private String tableName = FileBaseImport.this.tableName;
			private DBTypeConverter converter = typeConverter;

			@Override
			public void init() {

			}

			@Override
			public String[] processItems(String[] items) {
				return forEachItem(items);
			}

			@Override
			public String chooseLine(String line) {
				if (useCommentStr) {
					if (!line.startsWith(commentBeginStr)) {
						return line;
					}
					return null;
				} else {
					curLineNumber++;
					if (curLineNumber >= beginLineNum) {
						return line;
					}
					return null;
				}
			}

			@Override
			public String[] splitLine(String line) {
				String[] items;
				if (spliterType == LINE_SPLITER.COMMA) {
					items = commaCsv(line);
				} else {
					items = tabCsv(line);
				}
				if (hasAutoIncreasementId) {
					String[] newItems = new String[itemNum];
					for (int i = 0; i < items.length; i++) {
						newItems[i + 1] = items[i];
					}
					autoIncreasementId += 1;
					newItems[0] = Integer.toString(autoIncreasementId);
					return newItems;
				}
				return items;
			}

			@Override
			public void doPostOutside(String[] items) {
				if (items == null)
					return;
				// System.out.println(items[items.length-1]);
				if (items.length != itemNum) {
					throw new UnknownError("length is not equal to " + itemNum);
				} else {
					linkedList.add(items);
					if (linkedList.size() == batchImportNum) {
						dbHelper.insertBatch(tableName, linkedList, converter);
						counter += linkedList.size();
						linkedList.clear();
						logger.info(tableName + " insert " + counter
								+ " items...");
					}
				}
			}

			@Override
			public void cleanUp() {
				dbHelper.insertBatch(tableName, linkedList, converter);
				counter += linkedList.size();
				linkedList.clear();
				logger.info(tableName + " total insert " + counter + " items!");
			}
		}, fileType);

		dbHelper.disconnection();
	}

}
